package com.tcoding.client.privilege.user;

import com.jfoenix.controls.*;
import com.tcoding.client.gui.feature.FeatureResourceConsumer;
import com.tcoding.client.gui.feature.HideByFeature;
import com.tcoding.client.model.UserDataModel;
import com.tcoding.client.request.Request;
import com.tcoding.client.request.feign.admin.UserFeign;
import com.tcoding.client.utils.*;
import com.tcoding.core.entity.User;
import com.tcoding.core.util.DateUtils;
import io.datafx.controller.ViewController;
import io.datafx.controller.flow.action.ActionMethod;
import io.datafx.controller.flow.action.ActionTrigger;
import io.datafx.controller.flow.context.ActionHandler;
import io.datafx.controller.flow.context.FlowActionHandler;
import io.datafx.core.concurrent.ProcessChain;
import io.datafx.eventsystem.Event;
import io.datafx.eventsystem.OnEvent;
import javafx.collections.transformation.FilteredList;
import javafx.embed.swing.SwingFXUtils;
import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.image.Image;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.FileChooser;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.util.Callback;
import lombok.SneakyThrows;
import com.tcoding.core.vo.UserVO;
import org.apache.commons.lang3.StringUtils;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.imageio.ImageIO;
import javax.inject.Inject;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;

/**
 * @description:
 * @className: UserManagementController
 * @author: liwen
 * @date: 2020/3/4 21:05
 */
@ViewController(value = "/fxml/user/user_management.fxml", title = "用户管理")
public class UserManagementController {

    public static final String CONTENT_PANE = "ContentPane";

    @FXML
    private StackPane root;
    @FXML
    private VBox centPane;
    @FXML
    private StackPane spinnerPane;
    @FXML
    private TextField searchField;
    @FXML
    private TextField userNameTextField;
    @FXML
    private TextField accountTextField;
//    @FXML
//    private TextField pwdTextField;
    @FXML
    private TextArea descTextArea;
    @FXML
    private ComboBox genderCombobox;
    @FXML
    @ActionTrigger("createUser")
    @HideByFeature("userManager:btn_add")
    private Button addBut;
    @FXML
    @ActionTrigger("accept")
    private Button confirmButton;
    @FXML
    @ActionTrigger("cancel")
    private Button cancelButton;
    @FXML
    @ActionTrigger("search")
    private Button searchBut;


    @FXML
    private Pagination pagination;


    @FXML
    private TableView<UserVO> tableView;
    @FXML
    private TableColumn<UserVO, String> avatarColumn;
    @FXML
    private TableColumn<UserVO, String> serialNumberColumn;
    @FXML
    private TableColumn<UserVO, String> nameColumn;
    @FXML
    private TableColumn<UserVO, String> accountColumn;
    @FXML
    private TableColumn<UserVO, String> remarksColumn;
    @FXML
    private TableColumn<UserVO, String> lastUpdateTimeColumn;
    @FXML
    private TableColumn<UserVO, String> lastUpdatedByColumn;
    @FXML
    private TableColumn<UserVO, String> operateColumn;
    @FXML
    private JFXDialog userEditDialog;
    @FXML
    private JFXTextField nameTextField;
    @FXML
    private StackPane editUserAvatarPane;

    @FXML
    private Label userEditDialogLabel;

    private User editingUser;

    @ActionHandler
    private FlowActionHandler actionHandler;

    @Inject
    private UserDataModel dataModel;

    private FileChooser fileChooser;

    @Inject
    private FeatureResourceConsumer featureResourceConsumer;
    @PostConstruct
    public void init() throws Exception {
        fileChooser=new FileChooser();

        root.getChildren().remove(userEditDialog);
        editingUser = new User();
        featureResourceConsumer.consumeResource(this);
        spinnerPane.setVisible(false);
        serialNumberColumn.setCellFactory((col) -> {
            TableCell<UserVO, String> cell = new TableCell<UserVO, String>() {
                @Override
                public void updateItem(String item, boolean empty) {
                    super.updateItem(item, empty);
                    this.setText(null);
                    this.setGraphic(null);

                    if (!empty) {
                        int rowIndex = this.getIndex() + 1;
                        this.setText(String.valueOf(rowIndex));
                    }
                }
            };
            return cell;
        });
        searchBut.setGraphic(SvgGraphicUtil.buildSvgGraphic("search",12,Color.WHITE));

//        searchBut.setGraphic(SvgUtil.getSvg("car-outline",Color.WHITE));


        addBut.setGraphic(SvgGraphicUtil.buildSvgGraphic("plus",12,Color.WHITE));

        avatarColumn.setCellValueFactory(new PropertyValueFactory<>("avatar"));
        avatarColumn.setCellFactory((col) -> new TableCell<UserVO, String>() {
            @Override
            public void updateItem(String item, boolean empty) {

                super.updateItem(item, empty);
                this.setText(null);
                this.setGraphic(null);

                if (!empty) {
                    Image image;
                    if(StringUtils.isNotBlank(item)){

                        File f = null;
                        try {
                            f = File.createTempFile(UUID.randomUUID().toString(), ".png");
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        ImageUtil.GenerateImage(item,f);
                        if(f==null){
                            image = new Image(this.getClass().getResourceAsStream("/images/default-avatar.png"));
                        }else {
                            image=new Image(f.toURI().toString());
                        }
                    }else {
                        image = new Image(this.getClass().getResourceAsStream("/images/default-avatar.png"));
                    }

                    StackPane view = new StackPane();
                    view.setPrefWidth(50);
                    view.setPrefHeight(50);
                    BackgroundSize backgroundSize = new BackgroundSize(45, 45, false, false, true, false);
                    BackgroundImage backgroundImage = new BackgroundImage(image, BackgroundRepeat.NO_REPEAT, null, BackgroundPosition.CENTER, backgroundSize);
                    Background background = new Background(backgroundImage);
                    view.setBackground(background);
                    CFFXUtils.setClip(view, 6);
                    setGraphic(view);
                }
            }
        });

        nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
        accountColumn.setCellValueFactory(new PropertyValueFactory<>("userName"));
        remarksColumn.setCellValueFactory(new PropertyValueFactory<>("description"));
        lastUpdateTimeColumn.setCellValueFactory(new PropertyValueFactory<>("updTime"));
        lastUpdatedByColumn.setCellValueFactory(new PropertyValueFactory<>("updUser"));
        Callback<TableColumn<UserVO, String>, TableCell<UserVO, String>> cellFactory = new Callback<TableColumn<UserVO, String>, TableCell<UserVO, String>>() {
            @Override
            public TableCell<UserVO, String> call(TableColumn param) {

                final TableCell<UserVO, String> cell = new TableCell<UserVO, String>() {

                    private final ToggleButton resetBut = new ToggleButton();
                    private final ToggleButton editBut = new ToggleButton();
                    private final ToggleButton delBut = new ToggleButton();

                    {


                        resetBut.setTooltip(new Tooltip("重置密码"));
                        resetBut.getStyleClass().add("left-pill");
                        editBut.setTooltip(new Tooltip("编辑用户"));
                        editBut.getStyleClass().add("center-pill");
                        delBut.setTooltip(new Tooltip("删除用户"));
                        delBut.getStyleClass().add("right-pill");
                        try {
                            editBut.setGraphic(SvgGraphicUtil.buildSvgGraphic("pencil",12,Color.WHITE));
                            resetBut.setGraphic(SvgGraphicUtil.buildSvgGraphic("refresh",12,Color.WHITE));
                            delBut.setGraphic(SvgGraphicUtil.buildSvgGraphic("trash",12,Color.WHITE));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                        editBut.setOnMouseClicked(event -> {
                            tableView.getSelectionModel().select(getIndex());
                            toEditUser();
                        });
                        delBut.setOnMouseClicked(event -> {
                            tableView.getSelectionModel().select(getIndex());
                            delete();
                        });
                        resetBut.setOnMouseClicked(event -> {
                            tableView.getSelectionModel().select(getIndex());
                            restPassword();
                        });
                    }

                    @Override
                    protected void updateItem(String item, boolean empty) {
                        super.updateItem(item, empty);
                        if (empty) {
                            setGraphic(null);
                        } else {
                            HBox hBox = new HBox(resetBut, editBut, delBut);
                            hBox.setSpacing(0);
                            hBox.setAlignment(Pos.CENTER);
                            setGraphic(hBox);
                        }
                    }
                };
                return cell;
            }
        };

        operateColumn.setCellFactory(cellFactory);

        FilteredList<UserVO> filteredData = new FilteredList<>(dataModel.getUsers(), p -> true);
        tableView.setItems(filteredData);
        searchField.textProperty().addListener((o, oldVal, newVal) -> {
            filteredData.setPredicate(elementProp -> {
                if (newVal == null || newVal.isEmpty()) {
                    return true;
                }
                String val = Pinyin4jUtil.toPinYinLowercase(newVal);
                return Pinyin4jUtil.toPinYinLowercase(elementProp.getName()).contains(val)
                        || elementProp.getName().toLowerCase().contains(val)
                        || elementProp.getUserName().toLowerCase().contains(val);
            });
        });

        dataModel.selectedPersonIndexProperty().bind(tableView.getSelectionModel().selectedIndexProperty());
        pagination.pageCountProperty().bind(dataModel.pageCountProperty());
        //初始化分页
        pagination.setStyle("-fx-page-information-visible:false;");
        pagination.getStyleClass().add("cf-pagination-b");
        pagination.setPageFactory(param -> {
            showPage(param + 1);
            return tableView;
        });

        tableView.getStyleClass().addAll("cf-table-view", "cf-scroll-bar-style");

    }


    @SneakyThrows
    @ActionMethod("createUser")
    private void createUser() {
        userEditDialogLabel.setText("新增用户");
        nameTextField.setText("");
        userNameTextField.setText("");
        descTextArea.setText("");
        genderCombobox.getSelectionModel().select(0);
        editingUser.setId(null);
        initImageSelect(null);
        userEditDialog.show(root);
    }


    /**
     * 初始化编辑表单的图片
     * @param avatar
     */
    private void initImageSelect(String avatar){
        Image image;
        if(StringUtils.isNotBlank(avatar)){
            File f = null;
            try {
                f = File.createTempFile(UUID.randomUUID().toString(), ".png");
            } catch (IOException e) {
                e.printStackTrace();
            }
            ImageUtil.GenerateImage(avatar,f);
            if(f==null){
                image = new Image(this.getClass().getResourceAsStream("/images/default-avatar.png"));
            }else {
                image=new Image(f.toURI().toString());
            }
        }else {
            image = new Image(this.getClass().getResourceAsStream("/images/default-avatar.png"));
        }
        BackgroundSize backgroundSize = new BackgroundSize(45, 45, false, false, true, false);
        BackgroundImage backgroundImage = new BackgroundImage(image, BackgroundRepeat.NO_REPEAT, null, BackgroundPosition.CENTER, backgroundSize);
        Background background = new Background(backgroundImage);
        editUserAvatarPane.setBackground(background);
        editUserAvatarPane.setOnMouseClicked(e -> {
            File selectedFile  = fileChooser.showOpenDialog(root.getScene().getWindow());

            if (selectedFile != null) {
                File zipFile = null;
                try {
                    zipFile = File.createTempFile(UUID.randomUUID().toString(), ImageUtil.getSuffix(selectedFile));
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }
                //如果图片大小大于100k则压缩至100k
                 // 生成临时文件
                 try {
                     ImageUtil.compressUnderSize(selectedFile,1024*10,zipFile);
                 } catch (IOException ioException) {
                     ioException.printStackTrace();
                 }
                Image selectedImage = null;
                try {
                    selectedImage = new Image(new FileInputStream(zipFile));
                } catch (FileNotFoundException fileNotFoundException) {
                    fileNotFoundException.printStackTrace();
                }
                BackgroundSize newBackgroundSize = new BackgroundSize(45, 45, false, false, true, false);
                BackgroundImage newBackgroundImage = new BackgroundImage(selectedImage, BackgroundRepeat.NO_REPEAT, null, BackgroundPosition.CENTER, newBackgroundSize);
                Background newBackground = new Background(newBackgroundImage);
                editUserAvatarPane.setBackground(newBackground);
                zipFile.delete();
            }
        });
    }

    @ActionMethod("cancel")
    private void cancel() {
        userEditDialog.close();
    }

    @ActionMethod("accept")
    private void accept() {

        User user = new User();
        user.setName(nameTextField.getText());
        user.setDescription(descTextArea.getText());
        user.setUsername(userNameTextField.getText());
//        user.setPassword(pwdTextField.getText());
        user.setSex(genderCombobox.getSelectionModel().getSelectedIndex() == 0 ? "男" : "女");
        user.setId(editingUser.getId());
        List<BackgroundImage> images = editUserAvatarPane.getBackground().getImages();
        if(images!=null&&!images.isEmpty()){
            BackgroundImage backgroundImage = images.get(0);
            Image image = backgroundImage.getImage();

            BufferedImage bImage = SwingFXUtils.fromFXImage(image, null);
            ByteArrayOutputStream s = new ByteArrayOutputStream();
            String base64Image="";
            try {
                ImageIO.write(bImage, "png", s);
                byte[] res  = s.toByteArray();
                s.close();
                byte[] encode = Base64.getEncoder().encode(res);
                base64Image = new String(encode);
            } catch (IOException e) {
                e.printStackTrace();
            }
            user.setAvatar(base64Image);
        }



        ProcessChain.create()
                .addSupplierInExecutor(() -> {
                    if(user.getId()==null){
                        user.setPassword("123456");
                        Request.connector(UserFeign.class).add(user);
                    }else {
                        Request.connector(UserFeign.class).update(user.getId(), user);
                    }

                    return null;
                })
                .addConsumerInPlatformThread((rel) -> {
                    userEditDialog.close();
                    search();
                })
                .run();
    }

    private void restPassword() {
        UserVO userVO = dataModel.getUsers().get(dataModel.getSelectedPersonIndex());

        JFXAlert alert = new JFXAlert((Stage) root.getScene().getWindow());
        alert.initModality(Modality.APPLICATION_MODAL);
        alert.setOverlayClose(false);
        JFXDialogLayout layout = new JFXDialogLayout();
        layout.setHeading(new Label("消息提示"));
        layout.setBody(new Label("确定要重置【" + userVO.getUserName() + "】登录密码吗？"));
        JFXButton closeButton = new JFXButton("取消");
        closeButton.setOnAction(event -> alert.hideWithAnimation());
        JFXButton determineButton = new JFXButton("确定");
        determineButton.setOnAction(event -> {
            alert.hideWithAnimation();
            ProcessChain.create()
                    .addSupplierInExecutor(() -> Request.connector(UserFeign.class).restPassword(userVO.getId()))
                    .addConsumerInPlatformThread(result -> {

                    }).onException(e -> e.printStackTrace()).run();
        });
        layout.setActions(closeButton, determineButton);
        alert.setContent(layout);
        alert.show();
    }

    private void toEditUser(){

        userEditDialogLabel.setText("修改用户");
        UserVO userVO = dataModel.getUsers().get(dataModel.getSelectedPersonIndex());
        nameTextField.textProperty().bindBidirectional(userVO.nameProperty());
        userNameTextField.textProperty().bindBidirectional(userVO.userNameProperty());
//        pwdTextField.textProperty().bindBidirectional(userVO.userNameProperty());
        descTextArea.textProperty().bindBidirectional(userVO.descriptionProperty());
        String sex = userVO.sexProperty().getValue();
        genderCombobox.getSelectionModel().select("男".equals(sex) ? 0 : 1);
        editingUser.setId(userVO.getId());
        initImageSelect(userVO.getAvatar());
        userEditDialog.show(root);
    }


    private void delete() {
        UserVO userVO = dataModel.getUsers().get(dataModel.getSelectedPersonIndex());

        JFXAlert alert = new JFXAlert((Stage) root.getScene().getWindow());
        alert.initModality(Modality.APPLICATION_MODAL);
        alert.setOverlayClose(false);
        JFXDialogLayout layout = new JFXDialogLayout();
        layout.setHeading(new Label("消息提示"));
        layout.setBody(new Label("确实删除【" + userVO.getUserName() + "】吗？"));
        JFXButton closeButton = new JFXButton("取消");
        closeButton.setOnAction(event -> alert.hideWithAnimation());
        JFXButton determineButton = new JFXButton("确定");
        determineButton.setOnAction(event -> {
            alert.hideWithAnimation();
            ProcessChain.create()
                    .addSupplierInExecutor(() -> Request.connector(UserFeign.class).delete(userVO.getId()))
                    .addConsumerInPlatformThread(result -> {
                        if (result.isRel()) {
                            dataModel.getUsers().remove(dataModel.getSelectedPersonIndex());
                        }
                    }).onException(e -> e.printStackTrace()).run();
        });
        layout.setActions(closeButton, determineButton);
        alert.setContent(layout);
        alert.show();

    }


    private void showPage(Integer page) {
        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("keyId", searchField.getText());
        queryMap.put("page", page);
        query(queryMap);

    }

    @ActionMethod("search")
    private void search() {
        pagination.currentPageIndexProperty().setValue(0);

        Map<String, Object> queryMap = new HashMap<>();
        queryMap.put("keyId", searchField.getText());
        query(queryMap);

    }

    private void query(Map<String, Object> queryMap) {

        ProcessChain.create()
                .addRunnableInPlatformThread(() -> {
                    spinnerPane.setVisible(true);
                    centPane.setDisable(true);
                })
                .addSupplierInExecutor(() -> Request.connector(UserFeign.class).getPageList(queryMap)
                )
                .addConsumerInPlatformThread(result -> {
                    dataModel.getUsers().clear();
                    List<User> userList = result.getDatas();
                    dataModel.setPageCount((int) result.getTotal());

                    for (User user : userList) {
                        dataModel.getUsers().add(new UserVO(user.getId(), user.getName(), user.getUsername(),
                                DateUtils.formatDate(user.getUpdTime(), DateUtils.DATETIME_FORMAT),
                                user.getUpdUser(), user.getSex(), user.getDescription(),user.getAvatar()));
                    }
                })
                .withFinal(() -> {
                    spinnerPane.setVisible(false);
                    centPane.setDisable(false);
                })
                .onException(e -> e.printStackTrace())
                .run();
    }


    @PreDestroy
    private void destroy() {
        System.err.println("destroy " + this);
    }


    @FXML
    private void test() {
        System.err.println();
    }

    @OnEvent("refresh")
    private void onRefresh(Event<String> e) {
        System.err.println(this.getClass() + "\t" + e.getContent());

        search();

    }
}
